/**
 * 
 */
package kr.co.insoft.framework.config;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.GrantedAuthority;

/**
 * @author IN-SOFT Inc. GoodwillDD(sylee@in-soft.co.kr)
 * 
 */
public enum Menus {
	ROOT(Math.pow(2d, 27), -1, "", ""), /* 0 */
		ROOT_CLOUD(Math.pow(2d, 25), 0, "menu.root.cloud", ""), /* 1 */
			COST_COMPARSION(Math.pow(2d, 24), 1, "menu.comparison", "#"), /* 2 */ 
				COST_DASHBOARD(Math.pow(2d, 23), 2, "menu.comparison.dashboard", "/comparison/dashboard/view"), /* 3*/ 
				COST_MONTHLY(Math.pow(2d, 22), 2, "menu.comparison.monthly", "/comparison/monthly/view"),  /* 4 */
				COST_DALIY(Math.pow(2d, 21), 2, "menu.comparison.daily", "/comparison/daily/view"),  /* 5 */
				COST_PLANER(Math.pow(2d, 20), 2, "menu.comparison.planer", "/comparison/planer/view"), /* 6 */
			ORCHESTRATION(Math.pow(2d, 19), 1, "menu.orchestration", "#"), /* 7 */
				ORCHESTRATION_ORCHESTRATION(Math.pow(2d, 18), 7, "menu.orchestration.orchestration", "/orchestration/orchestration/main"), /* 8 */
			TEMPALTE(Math.pow(2d, 17), 1, "menu.template", "#"), /* 9 */
				TEMPALTE_APPLICATION(Math.pow(2d, 16), 9, "menu.template.application", "/template/application/lists"), /* 10 */
				TEMPALTE_SCRIPT(Math.pow(2d, 15), 9, "menu.template.script", "/template/script/lists"), /* 11 */
			EVENT_CHAIN(Math.pow(2d, 14), 1, "menu.eventchain", "#"), /* 12 */
				EVENT_CHAIN_EC(Math.pow(2d, 13), 12, "menu.eventchain.eventchain", "/eventchain/eventchain/main"), /* 13 */
			CONFIGRATION(Math.pow(2d, 12), 1, "menu.configration", "#"), /* 14 */ 
				CLOUD_VENDER(Math.pow(2d, 11), 14, "menu.configration.cloudvender", "/configration/vender/lists"), /* 15 */ 
				CLOUD_CONNECTION(Math.pow(2d, 10), 14, "menu.configration.cloudconnection", "/configration/connection/lists"), /* 16 */ 
				CDT(Math.pow(2d, 9), 14, "menu.configration.cdt", "/configration/cdt/lists"), /* 17 */ 
				SEV(Math.pow(2d, 8), 14, "menu.configration.sev", "/configration/sev/lists"),  /* 18 */
			NETWORK(Math.pow(2d, 7), 14, "menu.network", "#"), /* 19 */
				NETWORKTYPE(Math.pow(2d, 6), 14, "menu.network.networktype", "/network/networktype"), /* 19 */ 
				NETWORKTEMPLATE(Math.pow(2d, 5), 14, "menu.network.networktemplate", "/network/networktemplate"), /* 20 */
			MANGEMENT(Math.pow(2d, 4), 1, "menu.mgt", "#"), /* 21 */
				MANGEMENT_ACCOUNT(Math.pow(2d, 3), 21, "menu.mgt.account", "/mgt/account"), /* 22 */
				MANGEMENT_OMWACCOUNT(Math.pow(2d, 2), 21, "menu.mgt.omwaccount", "/mgt/omwaccount"), /* 23 */
				MANGEMENT_MENU(Math.pow(2d, 1), 21, "menu.mgt.menu", "/mgt/menu"), /* 24 */
				MANGEMENT_ROLE(Math.pow(2d, 0), 21, "menu.mgt.role", "/mgt/role"), /* 25 */
		ROOT_OMW(Math.pow(2d, 26), 0, "menu.root.omw", ""); /* 26 */

	Long menuid;
	int parentMenuid;
	String menuMsgName;
	String menuLink;

	static final int MENU_LENGTH = Menus.values().length;
	public static final String MENUS_COOKIE_NAME = "menuCookies";
	public static final String MENU_PREFIX = "M";
	public static final String authSeparator = "_";

	public static List<Menus> getNormalUserDefaultMenus() {
		List<Menus> auth = new ArrayList<Menus>();
		auth.add(ROOT);
		auth.add(ROOT_CLOUD);
		auth.add(COST_COMPARSION);
		auth.add(COST_DASHBOARD);
		auth.add(COST_MONTHLY);
		auth.add(COST_DALIY);
		auth.add(COST_PLANER);
		auth.add(ORCHESTRATION);
		auth.add(ORCHESTRATION_ORCHESTRATION);
		auth.add(TEMPALTE);
		auth.add(TEMPALTE_APPLICATION);
		auth.add(TEMPALTE_SCRIPT);
		auth.add(EVENT_CHAIN);
		auth.add(EVENT_CHAIN_EC);
		auth.add(CONFIGRATION);
		auth.add(CLOUD_VENDER);
		auth.add(CLOUD_CONNECTION);
		auth.add(CDT);
		auth.add(SEV);
		auth.add(NETWORK);
		auth.add(NETWORKTYPE);
		auth.add(NETWORKTEMPLATE);
		auth.add(ROOT_OMW);
		return auth;
	}
	
	public static List<Menus> getCompanyUserDefaultMenus() {
		List<Menus> auth = new ArrayList<Menus>();
		auth.add(ROOT);
		auth.add(ROOT_CLOUD);
		auth.add(COST_COMPARSION);
		auth.add(COST_DASHBOARD);
		auth.add(COST_MONTHLY);
		auth.add(COST_DALIY);
		auth.add(COST_PLANER);
		auth.add(ORCHESTRATION);
		auth.add(ORCHESTRATION_ORCHESTRATION);
		auth.add(TEMPALTE);
		auth.add(TEMPALTE_APPLICATION);
		auth.add(TEMPALTE_SCRIPT);
		auth.add(EVENT_CHAIN);
		auth.add(EVENT_CHAIN_EC);
		auth.add(CONFIGRATION);
		auth.add(CLOUD_VENDER);
		auth.add(CLOUD_CONNECTION);
		auth.add(CDT);
		auth.add(SEV);
		auth.add(NETWORK);
		auth.add(NETWORKTYPE);
		auth.add(NETWORKTEMPLATE);
		auth.add(ROOT_OMW);
		return auth;
	}
	
	private Menus(Double menuid, int parentMenuId, String menuMsgName,
			String menuLink) {
		this.menuid = menuid.longValue();
		this.parentMenuid = parentMenuId;
		this.menuMsgName = menuMsgName;
		this.menuLink = menuLink;
	}

	public int getParanetMenuId() {
		return this.parentMenuid;
	}

	public String getMenuMsgName() {
		return this.menuMsgName;
	}

	public String getMenuLink() {
		return this.menuLink;
	}

	public Long getMenuId() {
		return this.menuid;
	}

	public static Long getNormalUserMenuCodes() {
		return getAuthCode(getNormalUserDefaultMenus());
	}

	public static Long getCompanyUserMenuCodes() {
		return getAuthCode(getCompanyUserDefaultMenus());
	}

	/**
	 * 권한 코드(10진법)을 권한으로 decode하여 반환한다.
	 * 
	 * @param auth
	 * @return
	 */
	public static HashSet<Menus> getDecodeAuth(Long menuCode) {
		HashSet<Menus> result = new HashSet<Menus>();
		String tmp = getAuthBinary(menuCode);
		String[] authorities = tmp.split("|");
		for (Menus parsingAuth : values()) {
			if (authorities[parsingAuth.ordinal()].equals("1"))
				result.add(parsingAuth);
		}
		return result;
	}

	public static String getAuthBinary(Long authCode) {
		return StringUtils.leftPad(Long.toBinaryString(authCode), MENU_LENGTH,
				'0');
	}

	public static Long getAuthCode(Menus... menus) {
		HashSet<Menus> auth = new HashSet<Menus>(Arrays.asList(menus));
		Long sum = 0L;
		for (Menus tmp : auth)
			sum += tmp.menuid;
		return sum;
	}
	
	public static Long getAuthCode(List<Menus> menus) {
		HashSet<Menus> auth = new HashSet<Menus>(menus);
		Long sum = 0L;
		for (Menus tmp : auth)
			sum += tmp.menuid;
		return sum;
	}

	/**
	 * @param authorities
	 * @return
	 */
	public static HashSet<String> parseEnabledMenuIds(
			Collection<? extends GrantedAuthority> authorities) {
		HashSet<String> result = new HashSet<String>();
		String[] tmp = null;
		for (GrantedAuthority auth : authorities) {
			if (auth.getAuthority().startsWith(MENU_PREFIX)) {
				tmp = auth.getAuthority().split(authSeparator);
				tmp[0] = tmp[0].replace(MENU_PREFIX, "");
				if (Authorities.isEnabledViewAuth(tmp[1])) {
					for (Menus menu : getDecodeAuth(Long.parseLong(tmp[0]))) {
						result.add(Integer.toString(menu.ordinal()));
					}
				}
			}
		}
		return result;
	}

	/**
	 * @param string
	 * @return
	 */
	public static boolean isEnabledMenu(String menuCode, Menus menu) {
		return getDecodeAuth(Long.parseLong(menuCode)).contains(menu);
	}
}
